/**
 * @author liangxi
 * @since 2023/12/21
 */

#ifndef DESIGNPATTERN_GUMBALLMACHINE_H
#define DESIGNPATTERN_GUMBALLMACHINE_H

#include <iostream>

namespace State::Gumball {

    class GumballMachine {

    public:
        explicit GumballMachine(int count) : count(count) {
            if (this->count > 0) {
                state = NO_QUARTER;
            }
        }

        //投入25分钱
        void insertQuarter();

        //退回25分钱
        void ejectQuarter();

        //转动曲柄
        void turnCrank();

        //发放糖果
        void dispense();

    private:
        //状态机的状态
        const static int SOLD_OUT = 0;
        const static int NO_QUARTER = 1;
        const static int HAS_QUARTER = 2;
        const static int SOLD = 3;

        int state = SOLD_OUT;
        int count = 0;
    };

    void GumballMachine::insertQuarter() {
        if (this->state == HAS_QUARTER) {
            std::cout << "you can not insert another quarter" << "\n";
        } else if (this->state == NO_QUARTER) {
            this->state = HAS_QUARTER;
            std::cout << "you inserted a quarter" << "\n";
        } else if (this->state == SOLD_OUT) {
            std::cout << "you can not insert a quarter,the machine is sold out" << "\n";
        } else if (this->state == SOLD) {
            std::cout << "please wait,we are already giving you a gumball" << "\n";
        }
    }

    void GumballMachine::ejectQuarter() {
        if (state == HAS_QUARTER) {
            std::cout << "Quarter returned.\n";
        } else if (state == NO_QUARTER) {
            std::cout << "You have not inserted a quarter.\n";
        } else if (state == SOLD) {
            std::cout << "Sorry,you already turned the crank.\n";
        } else if (state == SOLD_OUT) {
            std::cout << "You can not eject, you have not inserted a quarter yet.\n";
        }
    }

    void GumballMachine::turnCrank() {
        if (state == SOLD) {
            std::cout << "Turning twice does not get you another gumball!\n";
        } else if (state == NO_QUARTER) {
            std::cout << "You turned but there is no quarter.\n";
        } else if (state == SOLD_OUT) {
            std::cout << "You turned, but there are no gumballs.\n";
        } else if (state == HAS_QUARTER) {
            std::cout << "You turned...\n";
            state = SOLD;
            dispense();
        }
    }

    void GumballMachine::dispense() {
        if (state == SOLD) {
            std::cout << "A gumball comes rolling out the slot\n";
            count = count - 1;
            if (0 == count) {
                std::cout << "Oops,out of gumballs!\n";
                state = SOLD_OUT;
            } else {
                state = NO_QUARTER;
            }
        } else if (state == NO_QUARTER) {
            std::cout << "You need to pay first\n";
        } else if (state == SOLD_OUT) {
            std::cout << "No gumball dispense\n";
        } else if (state == HAS_QUARTER) {
            std::cout << "No gumball dispense\n";
        }
    }

} // Gumball

#endif //DESIGNPATTERN_GUMBALLMACHINE_H
